/**
 * RetryMaxNumberOfTimesSpec.java
 * 
 * Created on Jun 30, 2008 at 2:39:15 PM
 */
package org.lego4j.policy;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.List;

import org.junit.Before;
import org.junit.Test;

/**
 * Specification for {@link RetryMaxNumberOfTimes}.
 * 
 * @author <a href="alexguev@gmail.com">Alexei Guevara</>
 * @version $Revision:$ updated on $Date:$ by $Author:$
 */
public class RetryMaxNumberOfTimesSpec {
    
    @SuppressWarnings("serial")
    static class A extends Exception {
    }
    @SuppressWarnings("serial")
    static class B extends A {
    }
    @SuppressWarnings("serial")
    static class C extends B {
    }

    private RetryMaxNumberOfTimes myPolicy;
    
    private int myMaxRetries;
    private long myDelayInMillis;
    
    @Before
    public void createPolicy() {
        this.myMaxRetries = 5;
        this.myDelayInMillis = 100; 
        
        List<Class<? extends Exception>> exceptions = new ArrayList<Class<? extends Exception>>();
        exceptions.add(B.class);
		this.myPolicy = new RetryMaxNumberOfTimes(exceptions, this.myMaxRetries, this.myDelayInMillis);
    }
    
    @Test
    public void shouldNotBeRecoverableBecauseExceptionTypeIsNotAnInstanceOfRecoverableType() {
        assertFalse( this.myPolicy.isExceptionRecoverable( new A() ) );
    }

    @Test
    public void shouldBeRecoverableBecauseExceptionTypeIsEqualsToRecoverableType() {
        assertTrue( this.myPolicy.isExceptionRecoverable( new B() ) );
    }
    
    @Test
    public void shouldBeRecoverableBecauseExceptionTypeIsSubClassOfRecoverableType() {
        assertTrue( this.myPolicy.isExceptionRecoverable( new C() ) );
    }

    @Test
    public void shouldReturnNegativeDelayBecauseMaxNumbersOfRetriesHaveBeenAttemptedAlready() {
        assertTrue( this.myPolicy.nextDelay( 0, this.myMaxRetries ) < 0 );
    }

    @Test
    public void shouldReturnPositiveDelayBecauseMaxNumbersOfRetriesHaveNotBeenAttempted() {
        assertTrue( this.myPolicy.nextDelay( 0, this.myMaxRetries - 1 ) == this.myDelayInMillis );
    }
    
    @Test
    public void shouldReturnPositiveDelayBecauseZeroRetriesHaveBeenAttempted() {
        assertTrue( this.myPolicy.nextDelay( 0, 0 ) == this.myDelayInMillis );
    }
    
    
    
}
